package com.freemalll.merchant.service.impl.coopManagement;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.freemalll.common.core.exception.BusinessException;
import com.freemalll.merchant.common.CommonEnum;
import com.freemalll.merchant.domain.dto.coopManagement.AssetManageDto;
import com.freemalll.merchant.domain.dto.coopManagement.AssetRateDetailEditDto;
import com.freemalll.merchant.domain.dto.coopManagement.AssetRateEditDto;
import com.freemalll.merchant.domain.dto.MerchantRateDto;
import com.freemalll.merchant.domain.entity.coopManagement.MerAssetLog;
import com.freemalll.merchant.domain.entity.coopManagement.MerAssetRateManage;
import com.freemalll.merchant.domain.dto.coopManagement.AssetManagePageDto;
import com.freemalll.merchant.domain.entity.coopManagement.MerAssetRateManageDetail;
import com.freemalll.merchant.domain.vo.coopManagement.AssetRatePageVo;
import com.freemalll.merchant.service.coopManagement.MerAssetLogService;
import com.freemalll.merchant.service.coopManagement.MerAssetRateManageDetailService;
import com.freemalll.merchant.mapper.coopManagement.MerAssetRateManageMapper;
import com.freemalll.merchant.service.coopManagement.MerAssetRateManageService;
import com.freemalll.merchant.utils.BeanUtils;
import com.freemalll.merchant.utils.DtoDiffUtil;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 服务层实现。
 *
 * @author songshixiong
 * @since 2025-05-16
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class MerAssetRateManageServiceImpl extends ServiceImpl<MerAssetRateManageMapper, MerAssetRateManage> implements MerAssetRateManageService {

    @Resource
    private MerAssetLogService merAssetLogService;
    @Resource
    private MerAssetRateManageDetailService merAssetRateManageDetailService;

    @Override
    public Page<AssetRatePageVo> pageSearch(AssetManagePageDto dto) {
        if (!StringUtils.hasText(dto.getQueryType())) {
            throw BusinessException.businessValidateError("请选择查询类型");
        }
        Page<AssetRatePageVo> assetRatePageVoPage;
        List<AssetRatePageVo> records;

        if (Objects.equals("YEAR", dto.getQueryType())) {
            assetRatePageVoPage = baseMapper.pageSearch(dto.page(), dto);
        } else {
            assetRatePageVoPage = baseMapper.pageSearchMonth(dto.page(), dto);
        }

        records = assetRatePageVoPage.getRecords();
        if (CollectionUtils.isEmpty(records)) {
            return assetRatePageVoPage;
        }

        List<String> rateIdList = records.stream()
                .map(AssetRatePageVo::getRateId)
                .collect(Collectors.toList());

        List<AssetRateDetailEditDto> rateManageDetails =
                "YEAR".equals(dto.getQueryType()) ?
                        merAssetRateManageDetailService.listByYear(rateIdList) :
                        merAssetRateManageDetailService.listByMonth(rateIdList);

        Map<String, List<AssetRateDetailEditDto>> map = rateManageDetails.stream()
                .collect(Collectors.groupingBy(AssetRateDetailEditDto::getRateId));

        for (AssetRatePageVo vo : records) {
            List<AssetRateDetailEditDto> details = map.get(vo.getRateId());
            if (!CollectionUtils.isEmpty(details)) {
                populatePhaseData(vo, details);
            }
        }

        return assetRatePageVoPage;
    }

    /**
     * 将明细数据按期数设置到对应的 VO 字段
     */
    private void populatePhaseData(AssetRatePageVo vo, List<AssetRateDetailEditDto> details) {
        for (AssetRateDetailEditDto detail : details) {
            switch (detail.getTimes()) {
                case 3:
                    vo.setPhaseThere(detail);
                    break;
                case 6:
                    vo.setPhaseSix(detail);
                    break;
                case 9:
                    vo.setPhaseNine(detail);
                    break;
                case 12:
                    vo.setPhaseTwelve(detail);
                    break;
                case 18:
                    vo.setPhaseEighteen(detail);
                    break;
                case 24:
                    vo.setPhaseTwentyFour(detail);
                    break;
                case 36:
                    vo.setPhaseThirtySix(detail);
                    break;
                default:
                    break;
            }
        }
    }


    @Override
    public void edit(List<AssetRateEditDto> list) {
        if (CollectionUtils.isEmpty(list)) {
            throw BusinessException.businessValidateError("请选择要编辑的费率");
        }
        boolean sourceFlag = list.stream().anyMatch(dto -> StringUtils.hasText(dto.getSourceId()));
        if (!sourceFlag) {
            throw BusinessException.businessValidateError("请先选择金融机构");
        }
        boolean flag = list.stream().anyMatch(dto -> StringUtils.hasText(dto.getRateId()));
        //新增
        if (!flag) {
            String templateCode = IdUtil.fastSimpleUUID();
            for (AssetRateEditDto dto : list) {
                MerAssetRateManage convert = new MerAssetRateManage();
                BeanUtils.copyPropertiesIgnoreNull(dto, convert);
                convert.setTemplateCode(templateCode);
                baseMapper.insert(convert);
                //生成费率明细
                merAssetRateManageDetailService.batchInsert(dto, convert.getRateId());
                MerAssetLog log = new MerAssetLog();
                log.setRelationId(templateCode);
                log.setLogDesc(CommonEnum.merchantAssetLogType.ADD.getDescription());
                log.setOperationType(CommonEnum.merchantAssetLogType.ADD.name());
                //记录操作日志
                merAssetLogService.save(log);
            }
            return;
        }
        if (list.size() == 1) {
            AssetRateEditDto assetRateEditDto = list.get(0);
            //通过rateId查询
            MerAssetRateManage oldRateManage = this.getById(assetRateEditDto.getRateId());
            //判断是否是从商月变成其他类型
            if (oldRateManage.getInterestAndFeeModel().equals(CommonEnum.interestAndFeeModelType.BUSINESS_MONTH.name())
                    && !assetRateEditDto.getInterestAndFeeModel().equals(CommonEnum.interestAndFeeModelType.BUSINESS_MONTH.name())) {
                List<MerAssetRateManage> merAssetRateManages = this.list(Wrappers.<MerAssetRateManage>lambdaQuery()
                        .eq(MerAssetRateManage::getSourceId, assetRateEditDto.getSourceId())
                        .eq(MerAssetRateManage::getInterestAndFeeModel, CommonEnum.interestAndFeeModelType.BUSINESS_MONTH.name()));
                // 获取数据库中已存在的 rateId 列表
                Set<String> existingRateIds = merAssetRateManages.stream()
                        .map(MerAssetRateManage::getRateId)
                        .collect(Collectors.toSet());

                // 获取需要保留的 rateId（即存在于 list 中的）
                Set<String> keepRateIds = list.stream()
                        .map(AssetRateEditDto::getRateId)
                        .filter(StringUtils::hasText)
                        .collect(Collectors.toSet());

                // 计算出需要删除的 rateId
                Set<String> deleteRateIds = existingRateIds.stream()
                        .filter(rateId -> !keepRateIds.contains(rateId))
                        .collect(Collectors.toSet());

                // 批量删除（推荐使用批量删除方法）
                if (!deleteRateIds.isEmpty()) {
                    this.remove(Wrappers.<MerAssetRateManage>lambdaQuery().in(MerAssetRateManage::getRateId, deleteRateIds));
                }
            }
        }


        //修改 修改资方
        Optional<String> result = list.stream()
                .map(AssetRateEditDto::getRateId)
                .filter(StringUtils::hasText)
                .findAny();
        if (result.isPresent()) {
            MerAssetRateManage merAssetRateManage = baseMapper.selectById(result.get());
            if (merAssetRateManage != null && !merAssetRateManage.getSourceId().equals(list.get(0).getSourceId())) {
                //校验资方是否已存在
                List<MerAssetRateManage> source = baseMapper.selectList(Wrappers.<MerAssetRateManage>lambdaQuery()
                        .eq(MerAssetRateManage::getSourceId, list.get(0).getSourceId()));
                if (!CollectionUtils.isEmpty(source)) {
                    throw BusinessException.businessOther("资方已存在");
                }
                //将原资方的数据查出来
                List<MerAssetRateManage> target = baseMapper.selectList(Wrappers.<MerAssetRateManage>lambdaQuery()
                        .eq(MerAssetRateManage::getSourceId, merAssetRateManage.getSourceId()));
                for (MerAssetRateManage dto : target) {
                    dto.setSourceId(list.get(0).getSourceId());
                    baseMapper.updateById(dto);
                }
                return;
            }
        }
        //编辑
        String templateCode = list.stream()
                .map(AssetRateEditDto::getTemplateCode)
                .filter(StringUtils::hasText)
                .findAny().orElse(null);
        if (templateCode == null) {
            templateCode = IdUtil.fastSimpleUUID();
        }
        for (AssetRateEditDto dto : list) {
            if (!StringUtils.hasText(dto.getRateId())) {
                MerAssetRateManage convert = new MerAssetRateManage();
                BeanUtils.copyPropertiesIgnoreNull(dto, convert);
                convert.setTemplateCode(templateCode);
                baseMapper.insert(convert);
                //生成费率明细
                merAssetRateManageDetailService.batchInsert(dto, convert.getRateId());
                MerAssetLog log = new MerAssetLog();
                log.setRelationId(templateCode);
                log.setLogDesc(CommonEnum.merchantAssetLogType.ADD.getDescription());
                log.setOperationType(CommonEnum.merchantAssetLogType.ADD.name());
                //记录操作日志
                merAssetLogService.save(log);
            } else {
                //编辑
                MerAssetRateManage old = baseMapper.selectById(dto.getRateId());
                if (old == null) {
                    throw BusinessException.businessOther("不存在编辑的数据");
                }
                MerAssetLog log = new MerAssetLog();
                AssetRateEditDto temp = new AssetRateEditDto();
                BeanUtils.copyPropertiesIgnoreNull(old, temp);
                List<MerAssetRateManageDetail> rateManageDetails = merAssetRateManageDetailService.list(Wrappers.<MerAssetRateManageDetail>lambdaQuery()
                        .eq(MerAssetRateManageDetail::getRateId, old.getRateId()));
                List<AssetRateDetailEditDto> details = new ArrayList<>();
                rateManageDetails.forEach(detail -> {
                    AssetRateDetailEditDto convert = Convert.convert(AssetRateDetailEditDto.class, detail);
                    details.add(convert);
                });
                //将list对象按照期数获取对应的对象放到temp中
                details.forEach(detail -> {
                    if (detail.getTimes().equals(3)) {
                        temp.setPhaseThere(detail);
                    } else if (detail.getTimes().equals(6)) {
                        temp.setPhaseSix(detail);
                    } else if (detail.getTimes().equals(9)) {
                        temp.setPhaseNine(detail);
                    } else if (detail.getTimes().equals(12)) {
                        temp.setPhaseTwelve(detail);
                    } else if (detail.getTimes().equals(18)) {
                        temp.setPhaseEighteen(detail);
                    } else if (detail.getTimes().equals(24)) {
                        temp.setPhaseTwentyFour(detail);
                    } else if (detail.getTimes().equals(36)) {
                        temp.setPhaseThirtySix(detail);
                    }
                });
                String changedFields = DtoDiffUtil.compareDtos(temp, dto);
                BeanUtils.copyPropertiesIgnoreNull(dto, old);
                baseMapper.updateById(old);
                merAssetRateManageDetailService.batchUpdate(dto);
                if (StringUtils.hasText(changedFields)) {
                    log.setRelationId(old.getTemplateCode());
                    log.setLogDesc(changedFields);
                    log.setOperationType(CommonEnum.merchantAssetLogType.EDIT.name());
                    //记录操作日志
                    merAssetLogService.save(log);
                }
            }
        }
    }


    @Override
    public void removeRate(String id) {
        if (!StringUtils.hasText(id)) {
            throw BusinessException.businessParamsNotExist("参数为空");
        }
        List<MerAssetRateManage> merAssetRateManages = baseMapper.selectList(Wrappers.<MerAssetRateManage>lambdaQuery().eq(MerAssetRateManage::getSourceId, id).or().eq(MerAssetRateManage::getTemplateCode, id));
        if (CollectionUtils.isEmpty(merAssetRateManages)) {
            throw BusinessException.businessParamsNotExist("该资方下没有费率");
        }
        baseMapper.delete(Wrappers.<MerAssetRateManage>lambdaQuery().eq(MerAssetRateManage::getSourceId, id).or().eq(MerAssetRateManage::getTemplateCode, id));
    }


    @Override
    public List<AssetRatePageVo> getRateList(AssetManageDto dto) {
        //场景分类映射
        if (dto.getSceneParentCategory().equals(CommonEnum.sceneCategory.DJK.name())) {
            dto.setSceneCategory(CommonEnum.supportingScenariosType.GREAT_HEALTH.name());
        } else {
            dto.setSceneCategory(CommonEnum.supportingScenariosType.EDUCATION.name());
        }
        List<AssetRatePageVo> rateList = baseMapper.getRateList(dto);
        if (CollectionUtils.isEmpty(rateList)) {
            return rateList;
        }
        List<String> rateIdList = rateList.stream()
                .map(AssetRatePageVo::getRateId)
                .collect(Collectors.toList());
        List<AssetRateDetailEditDto> rateManageDetails = merAssetRateManageDetailService.listByMonth(rateIdList);
        Map<String, List<AssetRateDetailEditDto>> map = rateManageDetails.stream()
                .collect(Collectors.groupingBy(AssetRateDetailEditDto::getRateId));

        for (AssetRatePageVo vo : rateList) {
            List<AssetRateDetailEditDto> details = map.get(vo.getRateId());
            if (!CollectionUtils.isEmpty(details)) {
                populatePhaseData(vo, details);
            }
        }
        boolean flag = rateList.stream().anyMatch(vo -> vo.getMinimumRate() == null || vo.getHighestRate() == null);
        if (flag) {
            String message;
            if (dto.getSceneParentCategory().equals(CommonEnum.sceneCategory.DJK.name())) {
                message = "大健康";
            } else {
                message = "教育";
            }
            throw BusinessException.businessOther("当前资方不支持" + message);
        }
        rateList.forEach(vo -> {
            if (StringUtils.hasText(vo.getSupportPeriods()) && vo.getSupportPeriods().contains("36")) {
                vo.setIsSupportPhaseThirtySix(true);
            }
        });
        return rateList;
    }

    @Override
    public List<MerchantRateDto> queryListBySourceId(List<String> sourceIds, String sceneCategory) {
        if (sceneCategory.equals(CommonEnum.sceneCategory.DJK.name())) {
            sceneCategory = CommonEnum.supportingScenariosType.GREAT_HEALTH.name();
        } else {
            sceneCategory = CommonEnum.supportingScenariosType.EDUCATION.name();
        }
        return baseMapper.queryListBySourceId(sourceIds, sceneCategory);
    }

}
